import random
import tkinter as tk
import tkinter.messagebox
from tkinter import *
from tkinter import messagebox
import time as cur_time
from datetime import datetime
import serial
from getModel import getModel
import chardet
from PIL import Image, ImageTk

# 箭头停止变量
toggleL = False
toggleR = False
# 需要刷新数据的操作,从串口读取数据
arduino_attr = {}
data_attr = {}
# 串口配置
port = "COM6"
bps = 9600  # 波特率，标准值之一：50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400,57600,115200
time = 1  # 超时设置,None：永远等待操作，0为立即返回请求结果，其他值为等待超时时间(单位为秒）
ser = ''


class MainWindow(tk.Tk):
    def __init__(self, *args, **kw):
        super().__init__()

        self.geometry("730x400+700+400")  # 设置窗口长宽和坐标

        # 窗口标题
        self.title('python_arduino串口通信')
        self.iconphoto(True, tk.PhotoImage(file="pictures/web.png"))

        # 添加标签
        message = "Arduino焊点"
        spot_arr = {0, 0, 0, 0, 0, 0}

        self.label1 = Label(self, text=message, font=("宋体", 15), fg="blue")
        spot_str = ""
        for i in spot_arr:
            i = str(i)
            spot_str += i
            spot_str += " "

        self.label1.place(x=35, y=5)

        # 添加Frame
        self.frame_left = tk.Frame(self, width=20, height=10, relief="solid", borderwidth=2)
        self.frame_left.place(x=5, y=30)
        self.leftLabel0 = Label(self.frame_left, text=0, font=18, relief="solid", width=5, height=3, padx=2)
        self.leftLabel0.grid(row=0, column=0, padx=15, pady=20)

        self.leftLabel1 = Label(self.frame_left, text=0, font=18, relief="solid", width=5, height=3, padx=2)
        self.leftLabel1.grid(row=0, column=1, padx=15, pady=20)

        self.leftLabel2 = Label(self.frame_left, text=0, font=18, relief="solid", width=5, height=3, padx=2)
        self.leftLabel2.grid(row=1, column=0)

        self.leftLabel3 = Label(self.frame_left, text=0, font=18, relief="solid", width=5, height=3, padx=2)
        self.leftLabel3.grid(row=1, column=1)

        self.leftLabel4 = Label(self.frame_left, text=0, font=18, relief="solid", width=5, height=3, padx=2)
        self.leftLabel4.grid(row=2, column=0, pady=20)

        self.leftLabel5 = Label(self.frame_left, text=0, font=18, relief="solid", width=5, height=3, padx=2)
        self.leftLabel5.grid(row=2, column=1)

        # 添加打开关闭按钮
        self.button1 = Button(self, text='打开串口', command=self.changeCom)
        self.button1.place(x=5, y=300)
        self.button2 = Button(self, text='关闭串口', command=self.changeCom)
        self.button2.place(x=80, y=300)

        # 显示图片并调整尺寸(注意这里默认支持的图片格式为GIF)
        image = Image.open('pictures/little_arrow.png')
        zoom = 0.2
        # multiple image size by zoom
        pixels_x, pixels_y = tuple([int(zoom * x) for x in image.size])
        self.images = (ImageTk.PhotoImage(image.resize((pixels_x, pixels_y))),
                       ImageTk.PhotoImage(Image.open('pictures/arrow1.png').resize((pixels_x, pixels_y))),
                       ImageTk.PhotoImage(Image.open('pictures/arrow1.png').resize((pixels_x, pixels_y))),
                       ImageTk.PhotoImage(Image.open('pictures/arrow1.png').resize((pixels_x, pixels_y))))

        self.labelArrow1 = Label(self, image=self.images[0], width=55, height=55)
        self.labelArrow1.place(x=200, y=100)

        self.label3 = Label(self, text="获取model焊点", font=("宋体", 15), fg="blue")
        self.label3.place(x=300, y=5)

        # 添加返回焊点的Frame
        self.frame_center = tk.Frame(self, width=20, height=10, relief="solid", borderwidth=2)
        self.frame_center.place(x=280, y=30)

        self.centerLabel0 = Label(self.frame_center, text='备1', font=18, fg='red',
                                  relief="solid", width=5, height=3, padx=2)
        self.centerLabel0.grid(row=0, column=0, padx=15, pady=20)
        self.centerLabel0.bind('<Button-1>', detail_coordinate)
        self.centerLabel1 = Label(self.frame_center, text='备2', font=18, fg='red', relief="solid", width=5, height=3,
                                  padx=2)
        self.centerLabel1.grid(row=0, column=1, padx=15, pady=20)
        self.centerLabel1.bind('<Button-1>', detail_coordinate)
        self.centerLabel2 = Label(self.frame_center, text='备3', font=18, fg='red', relief="solid", width=5, height=3,
                                  padx=2)
        self.centerLabel2.grid(row=1, column=0)
        self.centerLabel2.bind('<Button-1>', detail_coordinate)
        self.centerLabel3 = Label(self.frame_center, text='备4', font=18, fg='red', relief="solid", width=5, height=3,
                                  padx=2)
        self.centerLabel3.grid(row=1, column=1)
        self.centerLabel3.bind('<Button-1>', detail_coordinate)
        self.centerLabel4 = Label(self.frame_center, text='备5', font=18, fg='red', relief="solid", width=5, height=3,
                                  padx=2)
        self.centerLabel4.grid(row=2, column=0, pady=20)
        self.centerLabel4.bind('<Button-1>', detail_coordinate)
        self.centerLabel5 = Label(self.frame_center, text='备6', font=18, fg='red', relief="solid", width=5, height=3,
                                  padx=2)
        self.centerLabel5.grid(row=2, column=1)
        self.centerLabel5.bind('<Button-1>', detail_coordinate)

        self.labelArrow2 = Label(self, image=self.images[0], width=55, height=55)
        self.labelArrow2.place(x=475, y=100)

        self.label5 = Label(self, text="Arduino控制代码", font=("宋体", 15), fg="blue")
        self.label5.place(x=565, y=5)

        code = "arm3.movePose(\nspareDotInts[0], spareDotInts[1], \nspareDotInts[2], spareDotInts[3], \nspareDotInts[4]，spareDotInts[5], \nABS，MOVL);\n...}"
        self.label6 = Label(self, text=code, font=18, relief="solid", width=20, height=15, anchor='nw', wraplength=120)
        self.label6.place(x=555, y=30)
        # self.refreshData()
        self.mainloop()

    # 核心函数，负责从arduino串口和云端软件读取数据，并将对应的组件进行改变
    def refreshData(self):
        # 从arduino读取数据后赋给全局变量arduino_attr
        arduino_str = ComQuery()
        global arduino_attr
        if arduino_str != {}:
            print("arduino_str", arduino_str)  # 111101
            arduino_attr = cut(arduino_str, 1)
            # 更新焊点的错误信息
            for i in range(len(arduino_attr)):
                if arduino_attr[i] == '0':
                    if i == 0:
                        self.leftLabel0.configure(text='0', fg='red')
                    elif i == 1:
                        self.leftLabel1.configure(text='0', fg='red')
                    elif i == 2:
                        self.leftLabel2.configure(text='0', fg='red')
                    elif i == 3:
                        self.leftLabel3.configure(text='0', fg='red')
                    elif i == 4:
                        self.leftLabel4.configure(text='0', fg='red')
                    elif i == 5:
                        self.leftLabel5.configure(text='0', fg='red')
                else:
                    if i == 0:
                        self.leftLabel0.configure(text='1')
                    elif i == 1:
                        self.leftLabel1.configure(text='1')
                    elif i == 2:
                        self.leftLabel2.configure(text='1')
                    elif i == 3:
                        self.leftLabel3.configure(text='1')
                    elif i == 4:
                        self.leftLabel4.configure(text='1')
                    elif i == 5:
                        self.leftLabel5.configure(text='1')

            # 对箭头动画进行变化
            global toggleL, toggleR
            toggleL = True
            self.changeArrow(0)
            toggleR = True
            self.changeArrow(1)
            global data_attr
            # 从软件中读取补焊点后赋给全局变量data_attr
            get_model = getModel()
            data_attr = get_model.get_model()
            spare_dot = ''
            print(data_attr)
            if len(data_attr) != 0:
                spare_dot = [j['attrValue'] + ',' + j['attrLabel'][-1]
                             for j in data_attr['userAttr']
                             if '备用焊点' in j['attrLabel'] and str(1 + 1) in j['attrLabel']][0]
            print('spare_dot', spare_dot)
            send_model_to_serial(spare_dot)
            print("I Send SpareDot Back")
        # 代码...
        self.after(30, self.refreshData)  # 这里的100单位为毫秒。每隔100ms便会调用此函数

    # 改变箭头的图片实现动画效果
    def changeArrow(self, index):
        # 0，改变左边的箭头为绿色，1，改变右边的箭头为绿色
        if index == 0:
            if toggleL:
                self.labelArrow1.configure(image=self.images[int(cur_time.time() % 3)])
        else:
            if toggleR:
                self.labelArrow2.configure(image=self.images[int(cur_time.time() % 3)])

    # 打开关闭串口
    def changeCom(self):
        global ser
        if ser == '':
            try:
                ser = serial.Serial(port=port, baudrate=bps, bytesize=serial.EIGHTBITS, timeout=time)
            except:
                tkinter.messagebox.showinfo('warning', 'com6打开失败，请重试')
            else:
                print('Yes, Get COM 6')
                self.refreshData()
        elif ser.isOpen():
            ser.close()
            if ser.isOpen():
                tkinter.messagebox.showinfo('warning', 'com6关闭失败，请重试')
        else:
            ser.open()
            if not ser.isOpen():
                tkinter.messagebox.showinfo('warning', 'com6打开失败，请重试')


# 弹出小窗
def detail_coordinate(event):
    name = str(event.widget)
    if name == '.!frame2.!label':
        tkinter.messagebox.showinfo('I`m ok', data_attr['userAttr'][0]['attrValue'])
    elif name == '.!frame2.!label2':
        tkinter.messagebox.showinfo('I`m ok', data_attr['userAttr'][1]['attrValue'])
    elif name == '.!frame2.!label3':
        tkinter.messagebox.showinfo('I`m ok', data_attr['userAttr'][2]['attrValue'])
    elif name == '.!frame2.!label4':
        tkinter.messagebox.showinfo('I`m ok', data_attr['userAttr'][3]['attrValue'])
    elif name == '.!frame2.!label5':
        tkinter.messagebox.showinfo('I`m ok', data_attr['userAttr'][4]['attrValue'])
    else:
        tkinter.messagebox.showinfo('I`m ok', data_attr['userAttr'][5]['attrValue'])


# # 从串口读取数据
# def read_data_from_serial():
#     while True:
#         now = datetime.now()
#         every_time = now.strftime('%Y-%m-%d %H:%M:%S')  # 时间戳
#         data = ser.readline()
#         if data == "exit":  # 退出标志
#             break
#         else:
#             print(every_time, data)


# 向串口发送数据
def send_model_to_serial(send_data):
    if ser.isOpen():
        print(ser.portstr)
        ser.write(send_data.encode('utf-8'))


# 同串口COM6通讯，并返回相应的数组
def ComQuery():
    now = datetime.now()
    every_time = now.strftime('%Y-%m-%d %H:%M:%S')  # 时间戳
    data = ser.readline()

    # 如果data有特殊编码就进行转换
    if chardet.detect(data)["encoding"] == 'Windows-1252':
        data = data.decode('Windows-1252')
        print(every_time, data)
    else:
        data = data.decode()
        print(every_time, data)

    # 代表视觉传回了点位
    if "spot" in data:
        openMvNumString = data[12:18]
        for i in range(len(openMvNumString)):  # 循环遍历判断错点
            if openMvNumString[i] == '0':  #
                print("I Get Failed Spot,It`s not perfect")
                return openMvNumString

    if data == "get model done\r\n":
        send_model_to_serial("done")
    return {}


# 切割字符串
def cut(obj, sec):
    return [obj[i:i + sec] for i in range(0, len(obj), sec)]


if __name__ == '__main__':
    MainWindow = MainWindow()
